/**
 *  julive
 *
 *  Create by songli on 2021/05/24
 *  Copyright © 2021 居理买房网. All rights reserved.
 */

package domain

import (
	"context"
	"git.julive.com/julive/user/server/model"
	"git.julive.com/julive/user/server/proto/user"
	"git.julive.com/julive/user/server/repository"
	"git.julive.com/micro/pkg/dao"
	"git.julive.com/micro/pkg/logx"
	"go.uber.org/zap"
	"math"
)

type UserDomain interface {
	CreateUser(ctx context.Context, dto *user.User) error

	GetUserById(ctx context.Context, id int32) (*user.User, error)
	GetUserList(ctx context.Context, status, lastid, pagesize, page int32) (*user.UserList, error)

	UpdateUserStatus(ctx context.Context, id, status int32) (int64, error)
	UpdateUserCount(ctx context.Context, id, num int32, column string) (int64, error)

	DeleteUserById(ctx context.Context, id int32) (int64, error)
}

type userDomain struct {
	dao.Cache

	repo repository.UserRepository

	logger *zap.Logger
}

func NewUserDomain() UserDomain {
	logger := logx.Logger.With(zap.String("module", "user/domain"), zap.String("svc", "user"))
	repo := repository.NewUserRepository()
	dm := &userDomain{
		dao.NewCache(),
		repo,
		logger}
	return dm
}

func (dm *userDomain) CreateUser(ctx context.Context, dto *user.User) error {
	m := UserDtop(dto)
	return dm.repo.CreateUser(ctx, m)
}

func (dm *userDomain) GetUserById(ctx context.Context, id int32) (*user.User, error) {
	m, err := dm.repo.GetUserById(ctx, id)
	return UserPtod(m), err
}

func (dm *userDomain) GetUserList(ctx context.Context, status, lastid, pagesize, page int32) (*user.UserList, error) {
	list, total, err := dm.repo.GetUserList(ctx, status, lastid, pagesize, page)
	if err != nil {
		return nil, err
	}
	users := UserMap(list, UserPtod)

	var totalPage int32 = 0
	if total == 0 {
		page = 1
	} else {
		totalPage = int32(math.Ceil(float64(total) / float64(pagesize)))
	}
	userList := &user.UserList{}
	userList.Datalist = users
	userList.Total = int32(total)
	userList.TotalPage = totalPage
	userList.CurPage = page

	return userList, nil
}

func (dm *userDomain) UpdateUserStatus(ctx context.Context, id, status int32) (int64, error) {
	return dm.repo.UpdateUserStatus(ctx, id, status)
}

func (dm *userDomain) UpdateUserCount(ctx context.Context, id, num int32, column string) (int64, error) {
	return dm.repo.UpdateUserCount(ctx, id, num, column)
}

func (dm *userDomain) DeleteUserById(ctx context.Context, id int32) (int64, error) {
	return dm.repo.DeleteUserById(ctx, id)
}

func UserMap(pos []*model.User, fn func(*model.User) *user.User) []*user.User {
	var dtos = []*user.User{}
	for _, po := range pos {
		dtos = append(dtos, fn(po))
	}
	return dtos
}

func UserPtod(po *model.User) *user.User {
	if po == nil {
		return nil
	}

	dto := &user.User{}
	dto.Id = po.Id
	dto.Name = po.Name
	dto.ViewNum = po.ViewNum
	dto.Status = po.Status
	dto.CreateTime = po.CreateTime
	dto.UpdateDatetime = po.UpdateDatetime
	dto.CreateDatetime = po.CreateDatetime

	return dto
}

func UserDtop(dto *user.User) *model.User {
	if dto == nil {
		return nil
	}

	po := &model.User{}
	po.Id = dto.Id
	po.Name = dto.Name
	po.ViewNum = dto.ViewNum
	po.Status = dto.Status
	po.CreateTime = dto.CreateTime
	po.UpdateDatetime = dto.UpdateDatetime
	po.CreateDatetime = dto.CreateDatetime

	return po
}
